#include "MEFTestSuite.h"

#include <iostream>
#include <cassert>
#include <algorithm>

#include "MEFVector.h"
#include "MEFStack.h"
#include "MEFNode.h"
#include "MEFTreeIterator.h"
#include "MEFString.h"
#include "MEFXMLParser.h"
#include "MEFXMLTree.h"
#include "MEFXMLTag.h"
#include "MEFTree.h"
#include "MEFStringHash.h"
#include "MEFComponent.h"
#include "MEFGroup.h"
#include "MEFLayer.h"

using namespace std;

CMEFTestSuite::~CMEFTestSuite()
{
}

CMEFTestSuite::CMEFTestSuite()
{
}

void CMEFTestSuite::RunTestSuite()
{
	//testNode();
	//testStack();
	//testTreeIterator();
	//testVector();
	//testString();
	//testParser();
	testTree();
	//testNewTree();
	//testCDummyTree();
	testSortedTree();
	//testCMEFStringHash();
	
	testGUIComponent();
	testGUIGroup();
	testGUILayer();
}

void CMEFTestSuite::OnStartElement(const CMEFString& aType, const CMEFStringHash& aAttributes)
{
	//cout << "<" << aType;
	//for (unsigned int i=0; i < aAttributes.Size(); ++i)
	//{
	//	cout << " " << *aAttributes.At(i) <<"='" << *aValues.At(i) << "' "; 
	//}
	//cout <<  ">" << endl;
}

void CMEFTestSuite::OnEndElement(const CMEFString& aType)
{
	cout << "< /" << aType << ">" << endl; 
}

void CMEFTestSuite::OnText(const CMEFString& aText)
{
}

void CMEFTestSuite::testVector()
{
	cout << endl;
	cout << "******** Testing CMEFVector ***********";
	cout << endl;
	CMEFVector<int> myvector;

	myvector.PushBack(10);

	while (myvector.Back() != 0)
	{
		myvector.PushBack ( myvector.Back() -1 );
	}

	cout << "myvector contains:";
	for (unsigned i=0; i<myvector.Size() ; i++)
		cout << " " << myvector[i];

	cout << endl;
}

void CMEFTestSuite::testStack()
{
	cout << endl;
	cout << "******** Testing CMEFStack ***********";
	cout << endl;
	CMEFStack<int> mystack;

	for (int i=0; i<5; ++i) mystack.Push(i);

	cout << "Popping out elements...";
	while (!mystack.Empty())
	{
		cout << " " << mystack.Top();
		mystack.Pop();
	}
	cout << endl;
}

void CMEFTestSuite::testNode()
{
	cout << endl;
	cout << "******** Testing CMEFStack ***********";
	cout << endl;

	CMEFNode<int> node1(1);
	CMEFNode<int> node2(2);
	CMEFNode<int> node3(3);
	CMEFNode<int> node4(4);
	CMEFNode<int> node5(5);

	node3.AddChild(&node1);
	node3.AddChild(&node2);
	node1.AddChild(&node4);
	node2.AddChild(&node5);

	assert(node3.Item() == node1.Parent()->Item());
	assert(node3.Item() == node2.Parent()->Item());
	assert(2 == node3.NrOfChildren());
	assert(1 == node1.NrOfChildren());
	assert(1 == node1.NrOfChildren());
	assert(node3.GetChild(0)->Item() == 1);
	assert(node3.GetChild(1)->Item() == 2);

	cout << endl;
}

void CMEFTestSuite::testTreeIterator()
{
	cout << endl;
	cout << "******** Testing CMEFTreeIterator ***********";
	cout << endl;

	CMEFNode<int> node1(1);
	CMEFNode<int> node2(2);
	CMEFNode<int> node3(3);
	CMEFNode<int> node4(4);
	CMEFNode<int> node5(5);
	CMEFNode<int> node6(6);
	CMEFNode<int> node7(7);
	CMEFNode<int> node8(8);
	CMEFNode<int> node9(9);

	node3.AddChild(&node1);
	node3.AddChild(&node2);
	node1.AddChild(&node4);
	node2.AddChild(&node5);
	node9.AddChild(&node8);
	node9.AddChild(&node7);
	node9.AddChild(&node6);
	node2.AddChild(&node9);

	cout << "Printing the tree: ";
	CMEFTreeIterator<int> it(&node3);
	for(it.First(); !it.IsDone(); it.Next())
	{
		cout << it.CurrentItem() << " ";
	}		
	cout << endl;
}


void CMEFTestSuite::testString()
{
	cout << endl;
	cout << "******** Testing CMEFString ***********";
	cout << endl;
	CMEFString kalle("Kalle");
	CMEFString pelle("Pelle");

	cout <<kalle + pelle;
	cout << endl;
}

void CMEFTestSuite::testParser()
{
	cout << endl;
	cout << "******** Testing CMEFXMLParser ***********";
	cout << endl;

	CMEFXMLParser* parser = new CMEFXMLParser();

	parser->ParseFile("..\\Content\\XML\\ui.xml", *this);
	cout << endl;
}


template <class T>
void PrintLevelTree(CMEFTree<T>& aTree)
{
	CMEFTree<T>::iterator it = aTree.begin();
	CMEFTree<T>::iterator itEnd = aTree.end();

	while(it != itEnd)
	{
		for (int i=0; i<it->level(); i++)
		{
			cout << "  ";
		}

		cout << it->size() << "  " << it->value->Value() << endl;
		it++;
	}

	cout << endl;
}

void CMEFTestSuite::testTree()
{
	cout << endl;
	cout << "******** Testing CMEFXMLTree ***********";
	cout << endl;

		CMEFXMLTree tree;

	tree.BuildTree("..\\Content\\XML\\ui.xml");
	/*PrintLevelTree<CMEFXMLTag*>(tree.RootTree());*/

	//CMEFTree<CMEFXMLTag*>::iterator it = tree.RootTree().begin();
	//CMEFTree<CMEFXMLTag*>::iterator itEnd = tree.RootTree().end();

	//while(it != itEnd)
	//{
	//	for (int i=0; i<it->level(); i++)
	//	{
	//		cout << "  ";
	//	}

	//	cout << it->value->Type() << endl;
	//	it++;
	//}

	cout << endl;
}

void CMEFTestSuite::testNewTree()
{
	cout << endl;
	cout << "******** Testing New CMEFTree ***********";
	cout << endl;

	CMEFTree<int*> test(new int(1));
	test.push_back(new int(2));
	CMEFTree<int*>& back2 = test.back();
 	test.push_back(new int(3));
	test.push_back(new int(4));
	CMEFTree<int*>& back4 = test.back();

	back2.push_back(new int(5));
	back2.push_back(new int(6));
	back2.push_back(new int(7));
	back4.push_back(new int(8));
	back4.push_back(new int(9));

	CMEFTree<int*>::iterator it = test.begin();

	while (it != test.end())
	{
		cout << *it->value << ": is_root(" << it->is_root() << "), is_leaf(" << it->is_root() << "), " ;
		cout << "size(" << it->size() << "), degree(" << it->degree() << "), level(" << it->level() << ")\n";
		it++;
	}

	cout << endl;

	it = test.begin();
	while (it != test.end() && *it->value != 4)
	{
		it++;
	}

	cout << endl << *it->value <<endl;
	
	CMEFTree<int*>& back4_again(*it);

	it = back4_again.begin();
	while (it != back4_again.end())
	{
		cout << *it->value << ": is_root(" << it->is_root() << "), is_leaf(" << it->is_root() << "), " ;
		cout << "size(" << it->size() << "), degree(" << it->degree() << "), level(" << it->level() << ")\n";

		it++;
	}

	cout << endl;
}



class Cdummy
{
	static int counter; 
public:
	Cdummy()
	{		
		iInt = new int(counter++);
		cout << "CDummy(" << *iInt << ") created!\n";
	}
	~Cdummy()
	{
		cout << "CDummy(" << *iInt << ") deleted!\n";
		delete iInt;
	}

	inline int Value(){return *iInt;}
	
private:
	int* iInt;

};
int Cdummy::counter = 0;


void CMEFTestSuite::testCDummyTree()
{
	cout << endl;
	cout << "******** Testing testCDummyTree ***********";
	cout << endl;

	CMEFTree<Cdummy*> test(new Cdummy);
	test.push_back(new Cdummy);
	CMEFTree<Cdummy*>& back2 = test.back();
	test.push_back(new Cdummy);
	test.push_back(new Cdummy);

	test.back().push_back(new Cdummy);
	test.back().push_back(new Cdummy);
	test.back().push_back(new Cdummy);

	back2.push_back(new Cdummy);
	back2.push_back(new Cdummy);
	back2.back().push_back(new Cdummy);
	back2.back().push_back(new Cdummy);
	back2.back().push_back(new Cdummy);


	CMEFTree<Cdummy*>::iterator it = test.begin();
	while (it != test.end())
	{
		cout << it->value->Value() << ": is_root(" << it->is_root() << "), is_leaf(" << it->is_leaf() << "), " ;
		cout << "size(" << it->size() << "), degree(" << it->degree() << "), level(" << it->level() << ")\n";
		it++;
	}

	//Testing Delete
	it = test.begin();
	while (it != test.end())
	{
		delete it->value; 
		it++;
	}

	//Testing delete with a tree pointer
	CMEFTree<Cdummy*>* trePtr = new CMEFTree<Cdummy*>(new Cdummy);
	trePtr->push_back(new Cdummy);
	trePtr->push_back(new Cdummy);

	it = trePtr->begin();
	while (it != trePtr->end())
	{
		delete it->value; 
		it++;
	}
	delete trePtr;


	//Test creation wiht a tree pointer and a iterator;
	//Root
	CMEFTree<Cdummy*>* treePtr = new CMEFTree<Cdummy*>(new Cdummy);
	CMEFTree<Cdummy*>::iterator itPtr = treePtr->begin();
	

	//Start looking like an XML-tree structure
	itPtr->push_back(new Cdummy);
	itPtr->push_back(new Cdummy);
		itPtr = itPtr->back().begin();
		itPtr->push_back(new Cdummy);
			itPtr = itPtr->back().begin();
			itPtr->push_back(new Cdummy);
			itPtr->push_back(new Cdummy);
			itPtr->push_back(new Cdummy);
			itPtr->push_back(new Cdummy);
				itPtr = itPtr->back().begin();
				itPtr->push_back(new Cdummy);
			itPtr = itPtr->parent()->begin();
			itPtr->push_back(new Cdummy);
		itPtr = itPtr->parent()->begin();
		itPtr->push_back(new Cdummy);
			itPtr = itPtr->back().begin();
			itPtr->push_back(new Cdummy);
			itPtr->push_back(new Cdummy);
		itPtr = itPtr->parent()->begin();
		itPtr->push_back(new Cdummy);
	itPtr = itPtr->parent()->begin();
	itPtr->push_back(new Cdummy);
	itPtr->push_back(new Cdummy);
	itPtr->push_back(new Cdummy);

	itPtr = treePtr->begin();
	while (itPtr != treePtr->end())
	{
		cout << itPtr->value->Value() << ": is_root(" << itPtr->is_root() << "), is_leaf(" << itPtr->is_leaf() << "), " ;
		cout << "size(" << itPtr->size() << "), degree(" << itPtr->degree() << "), level(" << itPtr->level() << ")\n";
		itPtr++;
	}
}

bool myfunction (Cdummy* i,Cdummy* j) { return (i->Value() <j->Value()); }


void CMEFTestSuite::testSortedTree()
{
	
	cout << endl;
	cout << "******** Testing testCDummyTree ***********";
	cout << endl;

	CMEFTree<Cdummy*> test(new Cdummy);
	test.push_back(new Cdummy);
	CMEFTree<Cdummy*>& back2 = test.back();
	test.push_back(new Cdummy);
	test.push_back(new Cdummy);

	test.back().push_back(new Cdummy);
	test.back().push_back(new Cdummy);
	test.back().push_back(new Cdummy);

	back2.push_back(new Cdummy);
	back2.push_back(new Cdummy);
	back2.back().push_back(new Cdummy);
	back2.back().push_back(new Cdummy);
	back2.back().push_back(new Cdummy);

	CMEFTree<Cdummy*> test2(new Cdummy);
	test2.push_back(new Cdummy);
	test2.push_back(new Cdummy);
	test2.push_back(new Cdummy);
	test2.back().push_back(new Cdummy);
	test2.back().push_back(new Cdummy);
	test2.back().push_back(new Cdummy);

	cout << "*** test ****";
	cout << endl;
	PrintLevelTree<Cdummy*>(test);
	cout << "*** test2 ****";
	cout << endl;
	PrintLevelTree<Cdummy*>(test2);

	test.swap(test2);

	cout << "*** test ****";
	cout << endl;
	PrintLevelTree<Cdummy*>(test);
	cout << "*** test2 ****";
	cout << endl;
	PrintLevelTree<Cdummy*>(test2);

	test.begin()
		test.end()
	//sort(test.begin_child(), test.end_child(), myfunction);


	cout << "******** Test finshed! ***********";
	cout << endl;
}


void CMEFTestSuite::testCMEFStringHash()
{
	cout << endl;
	cout << "******** Testing testCDummyTree ***********";
	cout << endl;

	CMEFStringHash* hash = new CMEFStringHash;

	//Test adding elements
	assert(hash->Empty());
	assert(hash->Add("type", "fire"));
	assert(!hash->Add("type", "fire"));
	assert(hash->Add("id", "start"));
	assert(hash->Size() == 2);
	assert(hash->Add("x", "123"));
	assert(hash->Add("y", "432"));
	assert(!hash->Empty());
	assert(hash->Size() == 4);
	hash->Remove("y");
	assert(hash->Size() == 3);
	cout << hash->Find("type") << " " << hash->Find("id") <<  " " << hash->Find("x") << endl; 
	assert(hash->Find("type") == "fire");
	//Test 

	CMEFStringHash hash2;
	hash2 = *hash;
	cout << hash2.Find("type") << " " << hash2.Find("id") <<  " " << hash2.Find("x") << endl; 

	delete hash;

	cout << "******** Testing finshed! ***********";
	cout << endl;

}


void CMEFTestSuite::testGUIComponent()
{

}

void CMEFTestSuite::testGUIGroup()
{
}

void CMEFTestSuite::testGUILayer()
{
}